package com.lj.frame.config.auth;


import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lj.frame.consts.SessionKeys;
import com.lj.frame.jwt.JwtTokenUtil;
import com.lj.frame.jwt.SecretUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@RequiredArgsConstructor
@Configuration
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        //拦截是否服务器正在升级中
//        if(this.redisTemplate.hasKey(UPDATER_KEYS)){
//            return out(exchange.getResponse(), ResultCode.SERVER_MAINTENANCE);
//        }
//
        log.info("请求地址"+httpServletRequest.getRequestURI());

        //是否需要进行拦截
        if(!isFilter(httpServletRequest, httpServletResponse, object)){
            return true;
        }

        //检查token是否合法
        if (!checkToken(httpServletRequest, httpServletResponse, object)){
            writerError(httpServletResponse, "无效凭证,请登陆", 403);
            return false;
        }

        if (!checkPromise(httpServletRequest.getRequestURI(), httpServletRequest.getMethod())){
            writerError(httpServletResponse, "无相关权限", 403);
            return false;
        }
        return true;
    }


    /**
     * 是否需要过滤
     * */
    private boolean isFilter(HttpServletRequest request, HttpServletResponse response, Object object){
        //内部调用免登陆
        if(request.getHeader("server-name") != null){
            return false;
        }
        if (request.getMethod().equals(HttpMethod.OPTIONS.toString())){
            return false;
        }

        return true;
    }


    /**
     * 检查TOKEN值
     * */
    private boolean checkToken(HttpServletRequest request, HttpServletResponse response, Object object){

        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)){
            token = request.getHeader("Authorization");
        }

        String userKey = JwtTokenUtil.getUserInfo(token);
        if (Objects.isNull(userKey)){
            return false;
        }
        //查询redis中是否存在
        if (!stringRedisTemplate.hasKey(userKey)){
            return false;
        }

        String data = this.stringRedisTemplate.opsForValue().get(userKey);
        SecretUser secretUser = JSON.parseObject(data, SecretUser.class);
        if (secretUser == null || !token.equals(secretUser.getToken())) {
            return false;
        }
        //存入session中
        request.getSession().setAttribute(SessionKeys.USERINFO, secretUser);

        //刷新token过期时间
        if (StringUtils.hasLength(secretUser.getOpenId())) {
            //第三方登录，默认以REDIS到期为准
        } else {
            //更新过期时间
            this.stringRedisTemplate.expire(userKey, 30, TimeUnit.MINUTES);
        }

        return true;
    }


    /**
     * 检查权限
     * */
    private boolean checkPromise(String path, String method){
        return true;
//        //需要验证的接口
//        SecretUser secretUser = RequestUtils.getRequestUser();
//        String permission = path.replace("/api", "").replace("/", ":");
//        AntPathMatcher antPathMatcher = new AntPathMatcher();
//        List<String> permissionList = secretUser.getPermissionList();
//        for (String promise:permissionList){
//            //antPathMatcher.match()
//            if (promise.equals(permission)){
//                return true;
//            }
//        }
//        return false;
    }


    private void writerError(HttpServletResponse response, String msg, int code) throws IOException {
        //验证不通过
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);
        //将验证不通过的错误返回
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> resultMap = new HashMap<>(3);
        resultMap.put("code", code);
        resultMap.put("message", msg);
        resultMap.put("data", null);
        response.getWriter().write(mapper.writeValueAsString(resultMap));
    }


    /**
     * 注解方式  AOP
     * */
    private void checkversion1(){
                /*
        String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
        // 如果不是映射到方法直接通过
        if(!(object instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod=(HandlerMethod)object;
        Method method=handlerMethod.getMethod();
        //检查是否有passtoken注释，有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //检查有没有需要用户权限的注解
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                // 执行认证
                if (token == null) {
                    throw new RuntimeException("无token，请重新登录");
                }
                // 获取 token 中的 user id
                String userId;
                try {
                    userId = JWT.decode(token).getAudience().get(0);
                } catch (JWTDecodeException j) {
                    throw new RuntimeException("401");
                }
                User user = userService.findUserById(userId);
                if (user == null) {
                    throw new RuntimeException("用户不存在，请重新登录");
                }
                // 验证 token
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
                try {
                    jwtVerifier.verify(token);
                } catch (JWTVerificationException e) {
                    throw new RuntimeException("401");
                }
                return true;
            }
        }*/
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse,
                           Object o, ModelAndView modelAndView) throws Exception {

    }
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse,
                                Object o, Exception e) throws Exception {
    }
}
